/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.extensionpoints.palette;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.core.utils.IFilter;

/**
 * 
 */
public class Button extends MenuElement {
	
	/** debug channel */
	protected static final int channel = 21;

	/**
	 * 
	 */
	public final IConfigurationElement	configElement;
	
	/**
	 * 
	 */
	private final String label;
	
	/**
	 * 
	 */
	private final String tooltip;
	
	/**
	 * 
	 */
	private final String graphType;	
	
	/**
	 * 
	 */
	private final String iconPath;
	
	/**
	 * 
	 */
	private final String presentation;
	
	/**
	 * 
	 */
	private final String parentFilter;
	
	/**
	 * 
	 */
	private final String targetFilter;
	
	/**
	 * 
	 */
	private final Element element;

	/**
	 * 
	 */
	private IFilter parentFilterInstance = null;
	
	/**
	 * 
	 */
	private IFilter targetFilterInstance = null;
	
	/**
	 * 
	 */
	private boolean parentFilterRetrieved = false;
	
	/**
	 * 
	 */
	private boolean targetFilterRetrieved = false;	
	
	/**
	 * 
	 * 
	 * @param ordinal 
	 * @param configElt 
	 * 
	 * @return 
	 */
	public static Button parse(IConfigurationElement configElt, int ordinal) {
		
		if (!configElt.getName().equals(IConstants.TAG_BUTTON)) {
			return null;
		}
		
		try {
			return new Button(configElt);
			
		} catch (Exception e) {
			
			String name = configElt.getAttribute(IConstants.ATT_BUTTON_LABEL);
			if (name == null) {
				name = "[missing name attribute]";
			}
			String msg = "Failed to load button element named "
							+ name + " in "
							+ configElt
								.getDeclaringExtension()
								.getExtensionPointUniqueIdentifier();
			
			Debug.debug(null, msg, channel);
											
			return null;
		}
	}
	
	/**
	 * 
	 * 
	 * @param ordinal 	 * @param configElt 
	 */
	public Button(IConfigurationElement configElt) {
		this.configElement = configElt;

		label        = getAttribute(configElt, IConstants.ATT_BUTTON_LABEL, "undefined", true);
		tooltip      = getAttribute(configElt, IConstants.ATT_BUTTON_TIP, null, false);
		graphType    = getAttribute(configElt, IConstants.ATT_BUTTON_GRAPH, "NODE", true);
		iconPath     = getAttribute(configElt, IConstants.ATT_BUTTON_ICON, null, false);
		presentation = getAttribute(configElt, IConstants.ATT_BUTTON_PRESENTATION, "TEXT", true);
		parentFilter = getAttribute(configElt, IConstants.ATT_BUTTON_PARENT, null, false);
		targetFilter = getAttribute(configElt, IConstants.ATT_BUTTON_TARGET, null, false);

		// Retrieving element
		IConfigurationElement[] elementChildren = configElt.getChildren(IConstants.TAG_ELEMENT);
		if ((elementChildren == null) || (elementChildren.length != 1)) {
			element = null;
			return;
		}

		// Read 1st element
		Element proxy = Element.parse(elementChildren[0], 0);

		if (proxy != null) {
			element = proxy;
		} else {
			element = null;
		}
	}
	
	/**
	 * Default constructor.
	 * 
	 * @param uri 	 */
	public Button() {
		this.configElement = null;
		
		label        = "undefined";
		tooltip      = "undefined";
		graphType    = "undefined";
		iconPath     = "undefined";
		presentation = "undefined";
		parentFilter = "undefined";
		targetFilter = "undefined";
		element      = null;
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public Class getUMLType() {
		
		if (element == null) {
			Debug.debug(this, "Button::getUMLType() : no type defined for button "+label, channel);
			return null;
		} 
		
		String typeAsString = "org.eclipse.uml2.uml."+getElement().getType();
		
		try {
			Class umlType = Class.forName(typeAsString); 
			return umlType;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			Debug.log(e);
			return null;
		}
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public String getUMLTypeKind() {
		
		if ((element == null) || (element.getKind() == null)) {
			return null;
		} 
		
		return element.getKind();
	}
	
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public List<String> getUMLStereotypeNames() {
		
		if ((element == null) || (element.getStereotypes() == null)) {
			
			return new ArrayList<String>();
		} 
		
		List<String> stereotypeNames = new ArrayList<String>();
		Stereotype[] stereotypes = element.getStereotypes();
		
		for (int i = 0; i < stereotypes.length; i++) {
			stereotypeNames.add(stereotypes[i].getName());
		}

		return stereotypeNames;
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public ImageDescriptor getIconDescriptor() {

		ImageDescriptor iDesc;
		
		if ((getIconPath() == null)) {		
			return null;
		}
		
		String pluginId = configElement.getDeclaringExtension().getNamespaceIdentifier();
		iDesc = AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, getIconPath());

		return iDesc;
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	private IFilter getParentFilterInstance() {

		try {
			IFilter filterInstance = null;
			if (parentFilter != null) {

				filterInstance = (IFilter) configElement.createExecutableExtension(IConstants.ATT_BUTTON_PARENT);
			}
			
			return filterInstance;
			
		} catch (Exception e) {
			e.printStackTrace();
			Debug.log(e);
			return null;
		}
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	private IFilter getTargetFilterInstance() {

		try {
			IFilter filterInstance = null;
			if (targetFilter != null) {

				filterInstance = (IFilter) configElement.createExecutableExtension(IConstants.ATT_BUTTON_TARGET);
			}
			
			return filterInstance;
		} catch (Exception e) {
			e.printStackTrace();
			Debug.log(e);
			return null;
		}
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public Element getElement() {
		return element;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public String getIconPath() {
		return iconPath;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public String getLabel() {
		return label;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public IFilter getParentFilter() {
		if (parentFilterRetrieved) {
			return parentFilterInstance;
		}
		parentFilterRetrieved = true;
		parentFilterInstance = getParentFilterInstance();
		
		return parentFilterInstance;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public String getPresentation() {
		return presentation;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public IFilter getTargetFilter() {
		if (targetFilterRetrieved) {
			return targetFilterInstance;
		}
		targetFilterRetrieved = true;
		targetFilterInstance = getTargetFilterInstance();
		
		return targetFilterInstance;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public String getTooltip() {
		return tooltip;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public String getGraphType() {
		return graphType;
	}
}
